#include <task/abstract_task.h>

namespace task
{
AbstractTask::AbstractTask(const std::string &name)
    : task_name_(name), task_context_(nullptr), timeout_target_(0), timeout_flag_(false)
{
}
std::string AbstractTask::getName() const
{
    return task_name_;
}
void AbstractTask::pause()
{
    eventNotify(task::TaskEventType::PAUSE);
}
void AbstractTask::resume()
{
    eventNotify(task::TaskEventType::RESUME);
}
void AbstractTask::cancel()
{
    eventNotify(task::TaskEventType::CANCEL);
}
bool AbstractTask::isIdle() const
{
    TaskChainStatus task_chain_status;
    if (!getContextData<TaskChainStatus>("_work_ease_TASK_CHAIN_STATUS", task_chain_status))
    {
        EASE_WARN("cannot get task chin status, task name: %s", task_name_.c_str());
        return false;
    }
    return TaskChainStatus::TaskChainStatusIdle == task_chain_status;
}
bool AbstractTask::isRunning() const
{
    TaskChainStatus task_chain_status;
    if (!getContextData<TaskChainStatus>("_work_ease_TASK_CHAIN_STATUS", task_chain_status))
    {
        EASE_WARN("cannot get task chin status, task name: %s", task_name_.c_str());
        return false;
    }
    return TaskChainStatus::TaskChainStatusRunning == task_chain_status;
}
bool AbstractTask::isPause() const
{
    TaskChainStatus task_chain_status;
    if (!getContextData<TaskChainStatus>("_work_ease_TASK_CHAIN_STATUS", task_chain_status))
    {
        EASE_WARN("cannot get task chin status, task name: %s", task_name_.c_str());
        return false;
    }
    return TaskChainStatus::TaskChainStatusPause == task_chain_status;
}
void AbstractTask::onDone(bool res)
{

}
bool AbstractTask::onTimeout()
{
    return false;
}
void AbstractTask::onHalt()
{

}
bool AbstractTask::onReactive()
{
    return false;
}
void AbstractTask::startTimeout(int64_t timeoutMillSecond)
{
    timeout_flag_ = true;
    timeout_target_ = base::utils::DateTime::currentDateTime().addMillSecond(timeoutMillSecond).toMilliSecond();
}
void AbstractTask::stopTimeout()
{
    timeout_flag_ = false;
    timeout_target_ = 0;
}
bool AbstractTask::isTimeout() const
{
    if (!timeout_flag_)
    {
        return false;
    }
    auto currentDateTime = base::utils::DateTime::currentDateTime();
    return currentDateTime.toMilliSecond() > timeout_target_;
}
void AbstractTask::setContext(Context *ctx)
{
    task_context_ = ctx;
}
Context *AbstractTask::getContext()
{
    return task_context_;
}
void AbstractTask::setEventNotify(TaskEventNotify event_notify)
{
    std::lock_guard<std::mutex> lock_guard(event_notify_mutex_);
    event_notify_ = std::move(event_notify);
}
void AbstractTask::eventNotify(TaskEventType task_event_type)
{
    std::lock_guard<std::mutex> lock_guard(event_notify_mutex_);
    if (event_notify_)
    {
        event_notify_(task_event_type);
    }
    else
    {
        EASE_WARN("task: %s, event notify error, event type: %d", task_name_.c_str(), task_event_type);
    }
}
}
